Enhance PCX reader to handle (some) files from GPSUtil.
authorrobertl <robertl>
Thu, 23 Nov 2006 03:34:59 +0000 (03:34 +0000)
committerrobertl <robertl>
Thu, 23 Nov 2006 03:34:59 +0000 (03:34 +0000)
pcx.c
reference/gpsutil-1.pcx [new file with mode: 0644]
testo

diff --git a/pcx.c b/pcx.c
index b6c33d66d475b67efaa6c69f65b1e2d3dff8ac7e..3b75de0f0a3d438b19c39c11e8c9d63c359d3bea 100644 (file)
--- a/pcx.c
+++ b/pcx.c
@@ -2,7 +2,7 @@
     Access to Garmin PCX5 files.
     Format described in: http://www.garmin.com/manuals/PCX5_OwnersManual.pdf
 
-    Copyright (C) 2002-2005 Robert Lipe, robertlipe@usa.net
+    Copyright (C) 2002-2006 Robert Lipe, robertlipe@usa.net
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -22,6 +22,7 @@
 
 #include "defs.h"
 #include "garmin_tables.h"
+#include "csv_util.h"
 #include <ctype.h>
 
 static gbfile *file_in, *file_out;
@@ -30,7 +31,12 @@ static short_handle mkshort_handle2; /* for track and route names */
 static char *deficon = NULL;
 static char *cartoexploreur;
 static int read_as_degrees;
+static int read_gpsu;
 static int route_ctr;
+static int comment_col = 60;  /* This has a default */
+static int sym_col;
+static int lat_col;
+static int lon_col;
 
 #define MYNAME "PCX"
 
@@ -75,9 +81,8 @@ wr_deinit(void)
 static void
 data_read(void)
 {
-       char name[7], desc[40];
+       char name[7], desc[41];
        double lat,lon;
-       char latdir, londir;
        long alt; 
        int symnum;
        char date[10];
@@ -90,6 +95,8 @@ data_read(void)
        route_head *route = NULL;
        int n; 
        char lathemi, lonhemi;
+       char tbuf[20];
+       char nbuf[20];
 
        read_as_degrees  = 0;
 
@@ -100,19 +107,40 @@ data_read(void)
                
                switch (ibuf[0]) {
                case 'W': 
-                       sscanf(ibuf, "W  %6c %c%lf %c%lf %s %s %ld", 
-                               name, &latdir, &lat, &londir, &lon, 
-                               date, time, &alt);
+                       time[0] = 0;
+                       date[0] = 0;
+                       desc[0] = 0;
+                       alt = -9999;
+                       sscanf(ibuf, "W  %6c %s %s %s %s %ld", 
+                               name, tbuf, nbuf, date, time, &alt);
                        if (alt == -9999) {
                                alt = unknown_alt;
                        }
-                       sscanf(&ibuf[60], "%40c", 
-                               desc);
+
+                       if (comment_col) {
+                               strncpy(desc, &ibuf[comment_col], sizeof(desc)-1);
+                       } else {
+                               desc[0] = 0;
+                       }
+
+
                        symnum = 18;
-                       sscanf(&ibuf[116], "%d", 
-                               &symnum);
-                       desc[sizeof(desc)-1] = '\0';
+                       if (sym_col) {
+                               symnum = atoi(&ibuf[sym_col]);
+                       }
+
+                       // If we have explicit columns for lat and lon,
+                       // copy those entire words (warning: no spaces) 
+                       // into the respective coord buffers.
+                       if (lat_col) {
+                               sscanf(tbuf, "%s", ibuf + lat_col);
+                       }
+                       if (lon_col) {
+                               sscanf(nbuf, "%s", ibuf + lon_col);
+                       }
+
                        name[sizeof(name)-1] = '\0';
+                       desc[sizeof(desc)-1] = '\0';
                        
                        wpt_tmp = waypt_new();
                        wpt_tmp->altitude = alt;
@@ -126,12 +154,17 @@ data_read(void)
                        }
                        wpt_tmp->icon_descr = gt_find_desc_from_icon_number(symnum, PCX, NULL);
 
-                       if (latdir == 'S') lat = -lat;
-                       if (londir == 'W') lon = -lon;
-                       if (read_as_degrees) {
+                       if (read_as_degrees || read_gpsu) {
+                               human_to_dec(tbuf, &lat, &lon, 1);
+                               human_to_dec(nbuf, &lat, &lon, 2);
+                               
                                wpt_tmp->longitude = lon;
                                wpt_tmp->latitude = lat;
                        } else {
+                               lat = atof(&tbuf[1]);
+                               lon = atof(&nbuf[1]);
+                               if (tbuf[0] == 'S') lat = -lat;
+                               if (nbuf[0] == 'W') lon = -lon;
                                wpt_tmp->longitude = ddmm2degrees(lon);
                                wpt_tmp->latitude = ddmm2degrees(lat);
                        }
@@ -209,9 +242,42 @@ data_read(void)
                        break;
                case 'U': 
                        read_as_degrees = ! strncmp("LAT LON DEG", ibuf + 3, 11);
+                       if (strstr(ibuf, "UTM")) {
+                               fatal (MYNAME ": UTM is not supported.\n");
+                       }
+                       break;
+               // GPSU is apparently PCX but with a different definition 
+               // of "LAT LON DM" - unlike the other, it actually IS decimal
+               // minutes.
+               case 'I':
+                       read_gpsu = ! (strstr(ibuf, "GPSU") == NULL) ;
                        break;
+               // This is a format specifier.  Use this line to figure out
+               // where our other columns start.
+               case 'F': {
+                       int col;
+                       sym_col = 0;
+                       char *i = ibuf;
+                       for (col = 0, i = ibuf; *i; col++, i++) {
+                               if (0 == case_ignore_strncmp(i, "comment", 7)) {
+                                       comment_col = col;
+                               }
+                               if (0 == case_ignore_strncmp(i, "symbol", 6)) {
+                                       sym_col = col;
+                               }
+                               if (0 == case_ignore_strncmp(i, "latitude", 8)) {
+                                       lat_col = col;
+                               }
+                               if (0 == case_ignore_strncmp(i, "longitude", 9)) {
+                                       lon_col = col;
+                               }
+                       }
+               }
+               break;
                default:
+                       break;
                        ;
+               
                }
        }
 }
diff --git a/reference/gpsutil-1.pcx b/reference/gpsutil-1.pcx
new file mode 100644 (file)
index 0000000..26997a3
--- /dev/null
@@ -0,0 +1,23 @@
+H  SOFTWARE NAME & VERSION
+I  GPSU 4.20   01 REGISTERED to 'THIS FILE CREATED BY HAND FOR GPSBABEL TEST'
+S DateFormat=dd/mm/yyyy
+S Timezone=+01:00
+S Units=N,M
+S SymbolSet=0
+
+H R DATUM
+M E               WGS 84       100      0.0000000E+00   0.0000000E+00  0       0       0
+
+H  COORDINATE SYSTEM
+U  LAT LON DM
+
+F      ID----  Latitude        Longitude       T       O       Comment
+W      GCEBB   N35°58.3220'    W087°08.0820'   I       E       Mountain Bike Heaven by susy1313
+W      GC1A37  N36°05.4410'    W086°40.7730'   I       E       The Troll by a182pilot & Family
+W      GC1C2B  N35°59.7760'    W086°37.2070'   I       E       Dive Bomber by JoGPS & family
+W      GC25A9  N36°02.3090'    W086°38.9170'   I       E       FOSTER by JoGPS & Family
+W      GC2723  N36°06.7310'    W086°44.5060'   I       E       Logan Lighthouse by JoGps & Family
+W      GC2B71  N36°03.8450'    W086°47.4310'   I       E       Ganier Cache by Susy1313
+W      GC309F  N36°05.2660'    W086°48.5840'   I       E       Shy's Hill by FireFighterEng33
+W      GC317A  N36°03.4500'    W086°53.5200'   I       E       GittyUp by JoGPS / Warner Parks
+W      GC317D  N36°04.9680'    W086°52.0370'   I       E       Inlighting by JoGPS / Warner Parks
diff --git a/testo b/testo
index 9e09220a7dda9eac78d53de5bb731b469b061c22..d43841c42b34e8af223226ac2b9c48d44ba8d452 100755 (executable)
--- a/testo
+++ b/testo
@@ -159,6 +159,9 @@ compare ${TMPDIR}/mm.gps ${TMPDIR}/gu.wpt
 ${PNAME} -t -i gpx -f ${REFERENCE}/track/tracks.gpx -o pcx -F ${TMPDIR}/pcx.trk
 ${PNAME} -t -i pcx -f ${REFERENCE}/track/pcx.trk -o pcx -F ${TMPDIR}/pcx2.trk
 compare ${TMPDIR}/pcx.trk ${TMPDIR}/pcx2.trk 
+# GPSUtil strain - hand crafted, but based on problem report.
+${PNAME} -i pcx -f reference/gpsutil-1.pcx -o pcx -F ${TMPDIR}/mm-2.pcx
+compare ${TMPDIR}/mm-2.pcx ${TMPDIR}/mm.pcx
 
 #
 # Magellan file format